hvm: Respect irqbase set by protected mode in mode switching with VMXAssist.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 8 Jun 2007 10:19:55 +0000 (11:19 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 8 Jun 2007 10:19:55 +0000 (11:19 +0100)
RHEL4U4 PAE SMP guest currently crashes, and we found changeset 15214
introduced it. This patch fixes it.

Signed-off-by: Xin Li <xin.b.li@intel.com>
Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
tools/firmware/vmxassist/vm86.c
tools/firmware/vmxassist/vm86.h
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/hvm/vpic.c
xen/include/asm-x86/hvm/vmx/vmcs.h
xen/include/public/hvm/vmx_assist.h

index 78c1da0d88add2a7a7d991ce75bd3ae3d951227d..d702c031cc4b08bcdebbe01a4b5d1184f95635ed 100644 (file)
@@ -927,6 +927,7 @@ load_or_clear_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs
                load_seg(0, base, limit, arbytes);
 }
 
+static unsigned char rm_irqbase[2];
 
 /*
  * Transition to protected mode
@@ -936,6 +937,9 @@ protected_mode(struct regs *regs)
 {
        extern char stack_top[];
 
+       oldctx.rm_irqbase[0] = rm_irqbase[0];
+       oldctx.rm_irqbase[1] = rm_irqbase[1];
+
        regs->eflags &= ~(EFLAGS_TF|EFLAGS_VM);
 
        oldctx.eip = regs->eip;
@@ -1187,6 +1191,7 @@ outbyte(struct regs *regs, unsigned prefix, unsigned opc)
                        icw2[0] = 0;
                        printf("Remapping master: ICW2 0x%x -> 0x%x\n",
                                al, NR_EXCEPTION_HANDLER);
+                       rm_irqbase[0] = al;
                        al = NR_EXCEPTION_HANDLER;
                }
                break;
@@ -1200,6 +1205,7 @@ outbyte(struct regs *regs, unsigned prefix, unsigned opc)
                        icw2[1] = 0;
                        printf("Remapping slave: ICW2 0x%x -> 0x%x\n",
                                al, NR_EXCEPTION_HANDLER+8);
+                       rm_irqbase[1] = al;
                        al = NR_EXCEPTION_HANDLER+8;
                }
                break;
index ea8c2728d38f8fdf977e6970a8a78e39d58426f0..2cf3c0f7a5cb94cbcf9e224249c8551aa545f81f 100644 (file)
 
 #include <xen/hvm/vmx_assist.h>
 
-#define        NR_EXCEPTION_HANDLER    32
-#define        NR_INTERRUPT_HANDLERS   16
-#define        NR_TRAPS                (NR_EXCEPTION_HANDLER+NR_INTERRUPT_HANDLERS)
-
 #ifndef __ASSEMBLY__
 
 struct regs {
index 8a182025909610994d737079b1e1a298869e2135..366110d19dbabcf59ba798b915102edb3628c1d0 100644 (file)
@@ -2039,8 +2039,8 @@ enum { VMX_ASSIST_INVOKE = 0, VMX_ASSIST_RESTORE };
 static int vmx_assist(struct vcpu *v, int mode)
 {
     struct vmx_assist_context c;
-    u32 magic;
-    u32 cp;
+    struct hvm_hw_vpic *vpic = v->domain->arch.hvm_domain.vpic;
+    u32 magic, cp;
 
     /* make sure vmxassist exists (this is not an error) */
     if (hvm_copy_from_guest_phys(&magic, VMXASSIST_MAGIC_OFFSET,
@@ -2074,20 +2074,11 @@ static int vmx_assist(struct vcpu *v, int mode)
                 goto error;
             if ( vmx_world_restore(v, &c) != 0 )
                 goto error;
+            v->arch.hvm_vmx.pm_irqbase[0] = vpic[0].irq_base;
+            v->arch.hvm_vmx.pm_irqbase[1] = vpic[1].irq_base;
+            vpic[0].irq_base = NR_EXCEPTION_HANDLER;
+            vpic[1].irq_base = NR_EXCEPTION_HANDLER + 8;
             v->arch.hvm_vmx.vmxassist_enabled = 1;
-            /*
-             * The 32-bit vmxassist vm86.c support code is hard-coded to
-             * expect vPIC interrupts to arrive at interrupt traps 0x20-0x27
-             * and 0x28-0x2f.  It bounces these to 16-bit boot code traps
-             * 0x08-0x0f and 0x70-0x77.  But when the guest transitions
-             * to true native 32-bit mode, vmxassist steps out of the
-             * way and no such bouncing occurs; so we need to rewrite
-             * the vPIC irq base to point directly to 0x08/0x70 (see
-             * code just below).  So on re-entering 16-bit mode, we need
-             * to reset the vPICs to go back to the 0x20/0x28 bounce traps.
-             */
-            v->domain->arch.hvm_domain.vpic[0].irq_base = 0x20;
-            v->domain->arch.hvm_domain.vpic[1].irq_base = 0x28;
             return 1;
         }
         break;
@@ -2105,13 +2096,14 @@ static int vmx_assist(struct vcpu *v, int mode)
                 goto error;
             if ( vmx_world_restore(v, &c) != 0 )
                 goto error;
+            if ( v->arch.hvm_vmx.irqbase_mode ) {
+                vpic[0].irq_base = c.rm_irqbase[0] & 0xf8;
+                vpic[1].irq_base = c.rm_irqbase[1] & 0xf8;
+            } else {
+                vpic[0].irq_base = v->arch.hvm_vmx.pm_irqbase[0];
+                vpic[1].irq_base = v->arch.hvm_vmx.pm_irqbase[1];
+            }
             v->arch.hvm_vmx.vmxassist_enabled = 0;
-            /*
-             * See comment above about vmxassist 16/32-bit vPIC behaviour.
-             * The irq_base values are hard-coded into vmxassist vm86.c.
-             */
-            v->domain->arch.hvm_domain.vpic[0].irq_base = 0x08;
-            v->domain->arch.hvm_domain.vpic[1].irq_base = 0x70;
             return 1;
         }
         break;
index 5dfe1e4a6b9a22d539f9458194162dcf44946b60..19ef5d0756a5297d18419d27d49135855c58c9eb 100644 (file)
@@ -174,7 +174,8 @@ static int vpic_intack(struct hvm_hw_vpic *vpic)
     return irq;
 }
 
-static void vpic_ioport_write(struct hvm_hw_vpic *vpic, uint32_t addr, uint32_t val)
+static void vpic_ioport_write(
+    struct hvm_hw_vpic *vpic, uint32_t addr, uint32_t val)
 {
     int priority, cmd, irq;
     uint8_t mask;
@@ -265,6 +266,11 @@ static void vpic_ioport_write(struct hvm_hw_vpic *vpic, uint32_t addr, uint32_t
             vpic->imr = val;
             break;
         case 1:
+#if 1 /* Delete me when vmxassist is retired. */
+            /* Which mode is irqbase programmed in? */
+            current->arch.hvm_vmx.irqbase_mode =
+                current->arch.hvm_vmx.vmxassist_enabled;
+#endif
             /* ICW2 */
             vpic->irq_base = val & 0xf8;
             vpic->init_state++;
index 93383559c518ae3cbb13281e03fb59a3197b60b5..88063214b8106f8a9cf312b3e1d7c7b206086ed9 100644 (file)
@@ -79,7 +79,11 @@ struct arch_vmx_struct {
     unsigned long        cstar;
 #endif
     unsigned long        efer;
+
+    /* Following fields are all specific to vmxassist. */
     unsigned long        vmxassist_enabled:1;
+    unsigned long        irqbase_mode:1;
+    unsigned char        pm_irqbase[2];
 };
 
 struct vmcs_struct *vmx_alloc_host_vmcs(void);
index b07573c211fb4e539f103cbf4bbbd7ede955df64..4ef17febffe555ff0b6a87efd1d4c6f88ad2c675 100644 (file)
 
 #ifndef __ASSEMBLY__
 
+#define NR_EXCEPTION_HANDLER    32
+#define NR_INTERRUPT_HANDLERS   16
+#define NR_TRAPS        (NR_EXCEPTION_HANDLER+NR_INTERRUPT_HANDLERS)
+
 union vmcs_arbytes {
     struct arbyte_fields {
         unsigned int seg_type : 4,
@@ -98,6 +102,8 @@ struct vmx_assist_context {
     uint32_t  ldtr_limit;
     uint32_t  ldtr_base;
     union vmcs_arbytes ldtr_arbytes;
+
+    unsigned char rm_irqbase[2];
 };
 typedef struct vmx_assist_context vmx_assist_context_t;